#ifndef MLP_H_
#define MLP_H_

#include "Perceptron.h"
#include "DataSet.h"
#include "Chronometer.h"

/*
 * =====================================================================================
 *        Class:  MLP
 *  Description:  Classe que representa um Multi-Layer Perceptron
 * =====================================================================================
 */
class MLP
{

public:

    /*-----------------------------------------------------------------------------
     *  Carrega um MLP salvo no arquivo passado
     *-----------------------------------------------------------------------------*/
    MLP(const char *file);

    /*-----------------------------------------------------------------------------
     *  Constrói um MLP passando o número de variáveis de entrada e de saída,
     *  e a quantidades de neurônios em cada camada
     *-----------------------------------------------------------------------------*/
    MLP(uint nInVars, vuint& nNeurons);

    /*-----------------------------------------------------------------------------
     *  Salva o MLP em um arquivo
     *-----------------------------------------------------------------------------*/
    void saveToFile(const char *file);

    /*-----------------------------------------------------------------------------
     *  Treina o MLP passando um conjunto de entradas e saídas e o erro máximo permitido
     *-----------------------------------------------------------------------------*/
    void train(DataSet& ds, double tolerance, uint maxIt);

    /*-----------------------------------------------------------------------------
     *  Testa o MLP passando um conjunto de entradas
     *-----------------------------------------------------------------------------*/
    void test(DataSet& ds, double tolerance);

    /*-----------------------------------------------------------------------------
     *  Realiza o feedforward
     *-----------------------------------------------------------------------------*/
    vdoublePtr feedforward(vdoublePtr input);

    /*-----------------------------------------------------------------------------
     *  Realiza o feedbackward
     *-----------------------------------------------------------------------------*/
    void feedbackward(vdoublePtr expected);

    /*-----------------------------------------------------------------------------
     *  Imprime o MLP
     *-----------------------------------------------------------------------------*/
    void print();

private:

    /*-----------------------------------------------------------------------------
     *  Constrói um MLP
     *-----------------------------------------------------------------------------*/
    void build(CSVFilePtr csv = CSVFilePtr());

    /*-----------------------------------------------------------------------------
     *  Número de variáveis de entrada
     *-----------------------------------------------------------------------------*/
    uint nInVars;

    /*-----------------------------------------------------------------------------
     *  Número de variáveis de saída
     *-----------------------------------------------------------------------------*/
    uint nOutVars;

    /*-----------------------------------------------------------------------------
     *  Quantidade de camadas
     *-----------------------------------------------------------------------------*/
    uint nLayers;

    /*-----------------------------------------------------------------------------
     *  Aprendizado
     *-----------------------------------------------------------------------------*/
    LearningPtr learning;

    /*-----------------------------------------------------------------------------
     *  Quantidade de neurônios por camada
     *-----------------------------------------------------------------------------*/
    vuint nNeurons;

    /*-----------------------------------------------------------------------------
     *  Camadas
     *-----------------------------------------------------------------------------*/
    vector<PerceptronPtr> layers;

};

#endif /* MLP_H_ */
